﻿using System;

using Lucene.Net.Store;
using Lucene.Net.Store.Azure;

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

using mvcForum.SearchProvider.Lucene.Indexes;
using System.Configuration;

namespace MvcForum.Hosting.Azure {

	/// <summary>
	/// Directory resolver for Lucene and Azure.
	/// </summary>
	public class DirectoryResolver : IDirectoryResolver {
		/// <summary>
		/// The name of the Azure blob storage container to use for storing the Lucene indexes.
		/// </summary>
		private String catalogue;
		/// <summary>
		/// The Azure storage account to use to connect to the blob storage.
		/// </summary>
		private CloudStorageAccount account;

		/// <summary>
		/// Constructor for creating an Azure Directory Resolver.
		/// </summary>
		/// <param name="accountName">Azure account name</param>
		/// <param name="sharedKey">Azure storage shared key</param>
		/// <param name="catalogue">Catalogue to use for blob storage</param>
		/// <param name="useHttps">Should HTTPS be used</param>
		public DirectoryResolver(String accountName, String sharedKey, String catalogue, Boolean useHttps)
			: this(new CloudStorageAccount(new StorageCredentials(accountName, sharedKey), useHttps), catalogue) {
		}

		/// <summary>
		/// Constructor for creating an Azure Directory Resolver.
		/// </summary>
		/// <param name="catalogue">Catalogue to use for blob storage</param>
		public DirectoryResolver(String catalogue) :
			this(GetAccount(), catalogue) { }

		internal static CloudStorageAccount GetAccount() {
			CloudStorageAccount account = null;
			if (!CloudStorageAccount.TryParse(CloudConfigurationManager.GetSetting("MvcForum.StorageConnection"), out account)) {
				if (ConfigurationManager.ConnectionStrings["MvcForum.StorageConnection"] == null ||
					!CloudStorageAccount.TryParse(ConfigurationManager.ConnectionStrings["MvcForum.StorageConnection"].ConnectionString, out account)) {
					
					throw new ArgumentException("missing connection MvcForum.StorageConnection");
				}
			}
			if (account == null) {
				throw new ArgumentException("missing webrole setting MvcForum.StorageConnection");
			}
			return account;
		}

		/// <summary>
		/// Private constructor for creating an Azure Directory Resolver.
		/// </summary>
		/// <param name="account">Azure storage account to use</param>
		/// <param name="catalogue">Blob storage catalogue</param>
		private DirectoryResolver(CloudStorageAccount account, String catalogue) {
			this.account = account;
			this.catalogue = catalogue;

			// Get the client reference
			CloudBlobClient client = new CloudBlobClient(account.BlobEndpoint, account.Credentials);
			// Get the reference to the container
			CloudBlobContainer blobContainer = client.GetContainerReference(this.catalogue);

			// Create the container if it doesn't exist!
			if (blobContainer.CreateIfNotExists(BlobContainerPublicAccessType.Off)) {
				// Container was created, let's see permissions on it then!
				//blobContainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Off });
			}
		}

		/// <summary>
		/// Return the Azure directory for Lucene to use when indexing and searching.
		/// </summary>
		/// <returns></returns>
		public Directory GetDirectory() {
			// Create the Azure directory for Lucene with that given account and catalogue, using a RAM directory for local cache.
			return new AzureDirectory(account, this.catalogue, new Lucene.Net.Store.RAMDirectory());
		}
	}
}